package TpFinal;

import java.util.ArrayList;
import java.util.List;
import java.util.Queue;

public class Interseccion {

	private List<Celda> celdas = new ArrayList<Celda>();

	public Interseccion(Semaforo semaforoSur, Semaforo semaforoEste, Semaforo semaforoOeste){
		this.celdas = this.crearCuadrilla(semaforoEste,semaforoOeste,semaforoSur);
	}
	
	/**
	 * crea las celdas enumeradas para una matriz.
	 * tambien reemplaza 3 celdas por celdasDistinguidas con su respectivo semaforo
	 * @param semaforoEste
	 * @param semaforoOeste
	 * @param semaforoSur
	 * @return List<Celda>
	 */
	private List<Celda> crearCuadrilla(Semaforo semaforoEste, Semaforo semaforoOeste, Semaforo semaforoSur) {		
		List<Celda> cuadrilla = new ArrayList<Celda>();
		for(int x = 0 ; x <6 ; x++){			
			for(int y = 0 ; y<6 ; y++)
				cuadrilla.add(new Celda(x,y));			
		}
		this.ponerCeldasDistinguidas(cuadrilla, semaforoEste, semaforoOeste, semaforoSur);
		return cuadrilla;
	}	
	/**
	 * cambia 3 celdas por celdas distinguidas, las cuales tienen asociado un semaforo
	 * y elimina las celdas que ocupan esta posicion
	 * @param cuadrilla
	 * @param semaforoEste
	 * @param semaforoOeste
	 * @param semaforoSur
	 */
	private void ponerCeldasDistinguidas(List<Celda> cuadrilla, Semaforo semaforoEste, Semaforo semaforoOeste, Semaforo semaforoSur) {
		Celda celdaEste = this.darCeldaDe(cuadrilla, 5,1);
		Celda celdaOeste = this.darCeldaDe(cuadrilla, 0, 4);
		Celda celdaSur = this.darCeldaDe(cuadrilla, 4, 5);
		cuadrilla.add(cuadrilla.indexOf(celdaEste), new CeldaDistinguida(5, 1, semaforoEste));
		cuadrilla.remove(celdaEste);
		cuadrilla.add(cuadrilla.indexOf(celdaOeste), new CeldaDistinguida(0, 4, semaforoOeste));
		cuadrilla.remove(celdaOeste);
		cuadrilla.add(cuadrilla.indexOf(celdaSur), new CeldaDistinguida(4, 5, semaforoSur));
		cuadrilla.remove(celdaSur);
	}
	/**
	 * Devuelve la celda que tiene como posicion las coordenadas x,y
	 * de la coleccion de celdas que es pasada como parametro
	 * @param celdas
	 * @param x
	 * @param y
	 * @return Celda
	 */
	private Celda darCeldaDe(List<Celda> celdas, int x, int y) {
		for (Celda celda : celdas) {
			if(celda.getX() == x && celda.getY() == y){
				return celda;
			}
		}
		return null;
	}
	
	/**
	 * devuelve la celda que tiene la pocicion x,y igual a los parametros
	 * la celda es obtenia de las celdas que estan seteadas en la clase
	 * @param x
	 * @param y
	 * @return
	 */
	private Celda darCelda(int x, int y) {
		for (Celda celda : this.getCeldas()) {
			if(celda.getX() == x && celda.getY() == y){
				return celda;
			}
		}
		return null;
	}

	/**
	 * indica el camino dependiendo de la direccion origen y la direccion destino 
	 * hay 6 posibles caminos a recorrer. cada uno tiene su respectivo metodo de completado
	 * @param camino
	 * @param origen
	 * @param destino
	 */
	public void indicarCamino(Queue<Celda> camino, Direccion origen, Direccion destino) {
		if(Direccion.ESTE == origen && Direccion.OESTE == destino){
			this.completarCaminoEsteOeste(camino);
		}else if(Direccion.ESTE == origen && Direccion.SUR == destino){
			this.completarCaminoEsteSur(camino);
		}else if(Direccion.SUR == origen && Direccion.OESTE == destino){
			this.completarCaminoSurOeste(camino);
		}else if(Direccion.SUR == origen && Direccion.ESTE == destino){
			this.completarCaminoSurEste(camino);
		}else if(Direccion.OESTE == origen && Direccion.SUR == destino){
			this.completarCaminoOesteSur(camino);
		}else if(Direccion.OESTE == origen && Direccion.ESTE == destino){
			this.completarCaminoOesteEste(camino);
		}
	}

	/**
	 * Compelta el camino de oeste a este 
	 * agregando al parametro recibido las celdas que le corresponden
	 * @param camino
	 */
	private void completarCaminoOesteEste(Queue<Celda> camino) {
		camino.add(this.darCelda(0,4));
		camino.add(this.darCelda(1,4));
		camino.add(this.darCelda(2,4));
		camino.add(this.darCelda(3,4));
		camino.add(this.darCelda(4,4));
		camino.add(this.darCelda(5,4));
	}
	
	/**
	 * Compelta el camino de oeste a sur 
	 * agregando al parametro recibido las celdas que le corresponden
	 * @param camino
	 */
	private void completarCaminoOesteSur(Queue<Celda> camino) {
		camino.add(this.darCelda(0,4));
		camino.add(this.darCelda(1,4));
		camino.add(this.darCelda(1,5));
	}

	/**
	 * Compelta el camino de sur a este 
	 * agregando al parametro recibido las celdas que le corresponden
	 * @param camino
	 */
	private void completarCaminoSurEste(Queue<Celda> camino) {
		camino.add(this.darCelda(4,5));
		camino.add(this.darCelda(4,4));
		camino.add(this.darCelda(5,4));
	}

	/**
	 * Compelta el camino de sur a oeste 
	 * agregando al parametro recibido las celdas que le corresponden
	 * @param camino
	 */
	private void completarCaminoSurOeste(Queue<Celda> camino) {
		camino.add(this.darCelda(4,5));
		camino.add(this.darCelda(4,4));
		camino.add(this.darCelda(4,3));
		camino.add(this.darCelda(4,2));
		camino.add(this.darCelda(4,1));
		camino.add(this.darCelda(3,1));
		camino.add(this.darCelda(2,1));
		camino.add(this.darCelda(1,1));
		camino.add(this.darCelda(0,1));
	}

	/**
	 * Compelta el camino de este a sur
	 * agregando al parametro recibido las celdas que le corresponden
	 * @param camino
	 */
	private void completarCaminoEsteSur(Queue<Celda> camino) {
		camino.add(this.darCelda(5,1));
		camino.add(this.darCelda(4,1));
		camino.add(this.darCelda(3,1));
		camino.add(this.darCelda(2,1));
		camino.add(this.darCelda(1,1));
		camino.add(this.darCelda(1,2));
		camino.add(this.darCelda(1,3));
		camino.add(this.darCelda(1,4));
		camino.add(this.darCelda(1,5));
	}

	/**
	 * Compelta el camino de este a oeste 
	 * agregando al parametro recibido las celdas que le corresponden
	 * @param camino
	 */
	private void completarCaminoEsteOeste(Queue<Celda> camino) {
		camino.add(this.darCelda(5,1));
		camino.add(this.darCelda(4,1));
		camino.add(this.darCelda(3,1));
		camino.add(this.darCelda(2,1));
		camino.add(this.darCelda(1,1));
		camino.add(this.darCelda(0,1));
	}

	public enum Direccion{
		SUR,ESTE,OESTE;
	}

	public List<Celda> getCeldas() {
		return celdas;
	}

	public void setCeldas(List<Celda> celdas) {
		this.celdas = celdas;
	}
	
	
}
